// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "test_helper.h"

#include "macro_utils/macro_utils.h"

#include "pri_kb_test.h"

int run_pri_kb_tests(void)
{
    struct
    {
        uint64_t value;
        const char* value_as_string;
    } data[] = /*hand crafted values*/
    {
        {0, "0 B"},
        {1, "1 B"},


        /*1KB tests*/
        {1023, "1023 B"},
        {1024, "1 KB"},
        {1025, "1 KB"},

        {1024 + 102-1, "1 KB"},
        {1024 + 102+0, "1 KB"},
        {1024 + 102+1, "1.1 KB"},
        {1024 + 102+2, "1.1 KB"},
        {1024 + 204 - 1, "1.1 KB"},
        {1024 + 204 + 0, "1.1 KB"},
        {1024 + 204 + 1, "1.2 KB"},
        {1024 + 204 + 2, "1.2 KB"},

        {1024 + 307 - 1, "1.2 KB"},
        {1024 + 307 + 0, "1.2 KB"},
        {1024 + 307 + 1, "1.3 KB"},
        {1024 + 307 + 2, "1.3 KB"},

        {1024 + 409 - 1, "1.3 KB"},
        {1024 + 409 + 0, "1.3 KB"},
        {1024 + 409 + 1, "1.4 KB"},
        {1024 + 409 + 2, "1.4 KB"},

        {1024 + 511 - 1, "1.4 KB"},
        {1024 + 511 + 0, "1.4 KB"},
        {1024 + 511 + 1, "1.5 KB"},
        {1024 + 511 + 2, "1.5 KB"},

        {1024 + 614 - 1, "1.5 KB"},
        {1024 + 614 + 0, "1.5 KB"},
        {1024 + 614 + 1, "1.6 KB"},
        {1024 + 614 + 2, "1.6 KB"},

        {1024 + 716 - 1, "1.6 KB"},
        {1024 + 716 + 0, "1.6 KB"},
        {1024 + 716 + 1, "1.7 KB"},
        {1024 + 716 + 2, "1.7 KB"},

        {1024 + 819 - 1, "1.7 KB"},
        {1024 + 819 + 0, "1.7 KB"},
        {1024 + 819 + 1, "1.8 KB"},
        {1024 + 819 + 2, "1.8 KB"},

        {1024 + 921 - 1, "1.8 KB"},
        {1024 + 921 + 0, "1.8 KB"},
        {1024 + 921 + 1, "1.9 KB"},
        {1024 + 921 + 2, "1.9 KB"},

        {1024 + 1024 - 1, "1.9 KB"},
        {1024 + 1024 + 0, "2 KB"},

        /*2KB tests*/

        {2048 + 204 + 0, "2.1 KB"},
        {2048 + 204 + 1, "2.2 KB"},

        {2048 + 307 + 0, "2.2 KB"},
        {2048 + 307 + 1, "2.3 KB"},

        {2048 + 921 + 0, "2.8 KB"},
        {2048 + 921 + 1, "2.9 KB"},

        {2048 + 1024 - 1, "2.9 KB"},
        {2048 + 1024 + 0, "3 KB"},

        /*1023KB tests*/

        {1023*1024-1, "1022.9 KB"},
        {1023*1024+0, "1023 KB"},

        {1023 * 1024 + 512 - 1, "1023.4 KB"},
        {1023 * 1024 + 512 + 0, "1023.5 KB"},
        {1023 * 1024 + 512 + 1, "1023.5 KB"},

        /*1MB tests*/
        {1024 * 1024 - 1, "1023.9 KB"},
        {1024 * 1024 + 0, "1 MB"},
        {1024 * 1024 + 1, "1 MB"},

        {1153433, "1 MB"},
        {1153434, "1.1 MB"},
        {1153435, "1.1 MB"},

        {1024 * 1024 + (1024 * 1024/2)-1 , "1.4 MB"},
        {1024 * 1024 + (1024 * 1024 / 2) +0  , "1.5 MB"},
        {1024 * 1024 + (1024 * 1024 / 2) + 1  , "1.5 MB"},

        /*1GB tests*/
        {1024 * 1024 *1024 - 1 , "1023.9 MB"},
        {1024 * 1024 * 1024 +0 , "1 GB"},
        {1024 * 1024 * 1024 + 1 , "1 GB"},

        {1181116006,  "1 GB"},
        {1181116006 +1 ,  "1.1 GB"},

        {1024 * 1024 * 1024 + (1024 * 1024 * 1024 / 2) - 1 , "1.4 GB"},
        {1024 * 1024 * 1024 + (1024 * 1024 * 1024 / 2) + 0 , "1.5 GB"},
        {1024 * 1024 * 1024 + (1024 * 1024 * 1024 / 2) + 1 , "1.5 GB"},

        /*1TB-ish tests*/
        { 1024ULL * 1024 * 1024 *1024 - 1 , "1023.9 GB" },
        { 1024ULL * 1024 * 1024 * 1024 +0 , "1024 GB" },

        { 2 * 1024ULL * 1024 * 1024 * 1024 -1  , "2047.9 GB" },
        { 2 * 1024ULL * 1024 * 1024 * 1024 + 0 , "2048 GB" },

        { 10 * 1024ULL * 1024 * 1024 * 1024 -1 , "10239.9 GB" },
        { 10*1024ULL * 1024 * 1024 * 1024 + 0 , "10240 GB" },

    };

    char temp[100];

    {
        for(uint32_t i=0;i<sizeof(data)/sizeof(data[0]);i++)
        {
            (void)memset(temp, 0, sizeof(temp));
            int written = snprintf(temp, sizeof(temp), "%" PRI_KB "", KB_VALUE(data[i].value));
            POOR_MANS_ASSERT((written > 0) && (written < sizeof(temp)));
            POOR_MANS_ASSERT(strcmp(temp, data[i].value_as_string) == 0);
        }
    }

    return 0;
}
